package com.robert.BCH;

import java.util.Arrays;

public class polynomial {
    /**
     * 主要功能：多项式相关的处理，构造器、加法等
     */

    private int deg;//多项式的度
    private int[] nums;//多项式
    private final int mod = 2;

    /**
     *get方法
     */
    public int getDeg() {
        return deg;
    }

    public int[] getNums() {
        return nums;
    }

    /**
     * 构造器，输入字符串转多项式
     * @param n：字符串
     */
    public polynomial(String n){
        deg = n.length()-1;
        char[] c = n.toCharArray();
        int i = 0;
        while (c[i] == '0' && deg > 0){
            deg--;
            i++;
        }
        nums = new int[deg+1];
        int k = 0;
        while (k <= deg) {
            if (c[i] == '0') nums[k++] = 0;
            if (c[i] == '1') nums[k++] = 1;
            i++;
        }
    }

    /**
     * 构造器，输入数组转多项式
     * @param n 也可以输入数组构造多项式
     */
    public polynomial(int[] n){
        this.deg = n.length-1;
        int i=0;
        while (n[i]==0 && deg > 0) {
            this.deg--;
            i++;
        }
        int k = 0;
        nums = new int[deg+1];
        while(k<=this.deg){
            nums[k] = n[i];
            k++;
            i++;
        }
    }

    /**
     * 输入一个多项式，在前面添加s个0
     * @param s 整数
     */
    public int[] extend(int s){
        int d = s+deg;
        int[] ans = new int[d+1];
        for(int i=s;i<d+1;i++){
            ans[i] = nums[i-s];
        }
        return ans;
    }

    /**
     * 多项式加法，输入多项式b，输出加法之后的结果多项式对象
     * @param b 多项式
     * @return polynomial
     */
    public polynomial add(polynomial b){
        int ai = deg;
        int bi = b.deg;
        int max = Math.max(deg,b.deg);
        int[] ans = new int[max+1];
        for(int i=max;i>=0;i--){
            if(ai<0) {
                ans[i] = b.getNums()[bi];
                bi--;
                continue;
            }
            if(bi<0){
                ans[i] = nums[ai];
                ai--;
                continue;
            }
            ans[i] = (nums[ai] + b.getNums()[bi])%mod;
            ai--;
            bi--;
        }
        return new polynomial(ans);
    }

    /**
     * 多项式乘法
     * @param b 多项式
     * @return
     */
    public polynomial multiply(polynomial b){
        int nDeg = this.deg + b.deg;
        int[] nans = new int[nDeg+1];
        for(int i=0;i<b.deg+1;i++){
            if(b.getNums()[i]==0) continue;
            for(int j=0;j<this.deg+1;j++){
                nans[i+j] = (nans[i+j] + nums[j])%mod;
            }
        }
        return new polynomial(nans);
    }

    /**
     * 多项式拼接
     * @param b 多项式
     */
    public polynomial concat(polynomial b){
        int nDeg = this.deg + b.deg +1;
        int[] nans = new int[nDeg+1];
        for(int i=0;i<nDeg+1;i++){
            if(i>this.deg){
                nans[i] = b.getNums()[i-this.deg-1];
            }else {
                nans[i] = this.nums[i];
            }
        }
        return new polynomial(nans);
    }

    /**
     * 判断多项式是否为0
     */
    public boolean isZero(){
        for(int i=0;i<deg+1;i++){
            if(nums[i]!=0) return false;
        }
        return true;
    }

    /**
     * 模多项式
     */
    public polynomial mod(polynomial b){
        if(this.deg<b.deg) return this;
        int[] ans = new int[b.deg+1];
        polynomial copyNum = new polynomial(nums);
        for (int i=0;i<this.deg-b.deg+1;i++){
            if(copyNum.getNums()[i]==0) continue;
            for(int j=0;j<b.deg+1;j++){
                copyNum.getNums()[i+j] = (copyNum.getNums()[i+j] + b.getNums()[j])%2;
            }
        }
        int i = this.deg;
        for(int j=b.deg;j>=0;j--){
            ans[j] = copyNum.getNums()[i--];
        }
        return new polynomial(ans);
    }

    /**
     * 多项式除法
     */
    public polynomial divide(polynomial b){
        if(this.deg<b.deg) return new polynomial("0");
        int[] ans = new int[this.deg-b.deg+1];
        polynomial copyNum = new polynomial(nums);
        for (int i=0;i<this.deg-b.deg+1;i++){
            if(copyNum.getNums()[i]==0){
                continue;
            }
            for(int j=0;j<b.deg+1;j++){
                copyNum.getNums()[i+j] = (copyNum.getNums()[i+j] + b.getNums()[j])%2;
            }
            ans[i] = 1;
        }
        return new polynomial(ans);
    }

    /**
     * 转成字符串
     */
    public String toString(){
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i <= deg; i++) {
            switch (nums[i]) {
                case 0 -> sb.append("0");
                case 1 -> sb.append("1");
            }
        }
        return sb.toString();
    }

    /**
     * 判断多项式是否相等
     */
    public boolean equals(polynomial b){
        return Arrays.equals(nums, b.nums);
    }
}